package com.zha.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.zha.constant.ManagerConstants;
import com.zha.domain.SysMenu;
import com.zha.mapper.SysMenuMapper;
import com.zha.service.SysMenuService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Title: 只有光头才能变强
 * @Author: 炸炸
 * @Date: 2024/12/16 9:46
 */
@Service
public class SysMenuServiceImpl implements SysMenuService {

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public Set<SysMenu> querySysUserListById(Long userId) {
        // 从redis中获取菜单权限集合
        String jsonStr = stringRedisTemplate.opsForValue().get(ManagerConstants.LOGIN_SYS_MENU_PREDIX + userId);
        // 判断是否有值
        Set<SysMenu> menus = null;
        if (StringUtils.hasText(jsonStr)){
            // 有:直接使用,需要将json格式的字符串转换为集合
            List<SysMenu> sysMenus = JSONObject.parseArray(jsonStr, SysMenu.class);
            // 将list集合转换为set集合
            menus = sysMenus.stream().collect(Collectors.toSet());
        }else {
            // 没有:从数据库中查询,并存入redis中,并返回
            menus = sysMenuMapper.selectSysMenuListByUserId(userId);
            stringRedisTemplate.opsForValue().set(ManagerConstants.LOGIN_SYS_MENU_PREDIX + userId, JSONObject.toJSONString(menus));
        }
        // 将集合转换为树结构

        return transformToTree(menus,0L);
    }

    /**
     * 集合转换为树,分为两种情况:
     * 1. 已知菜单深度<=2
     * 2. 未知菜单深度
     * @param menus  菜单权限集合
     * @param pId    父菜单id
     * @return     树结构菜单集合
     */
    private Set<SysMenu> transformToTree(Set<SysMenu> menus, long pId) {
        // 已知菜单深度<=2
        // 获取根目录
       /* Set<SysMenu> roots = menus.stream().
                filter(menu -> menu.getParentId().equals(pId))
                .collect(Collectors.toSet());
        // 循环遍历根目录
        roots.forEach(r -> {
            // 从菜单集合中过滤出其节点的父节点值与当前根节点的id值一致的节点集合
            Set<SysMenu> child = menus.stream().
                    filter(m -> m.getParentId().equals(r.getMenuId()))
                    .collect(Collectors.toSet());
            r.setList(child);
        });
        return roots;*/
        // 未知菜单深度
        // 获取根目录
        Set<SysMenu> roots = menus.stream().
                filter(menu -> menu.getParentId().equals(pId))
                .collect(Collectors.toSet());
        // 获取子节点集合
        roots.forEach(r -> r.setList(transformToTree(menus, r.getMenuId())));
        return roots;
    }
}
